/**
 * 
 */
package fr.toussna.dao;

import java.util.List;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.Assert;
import org.testng.annotations.Test;

import fr.toussna.entity.Article;
import fr.toussna.entity.Category;
import fr.toussna.entity.Comment;
import fr.toussna.entity.DomainEntity;
import fr.toussna.exception.ObjectNotFoundException;
import fr.toussna.utils.EntityFactory;

/**
 * Testing CategoryDAO
 * 
 * @author My
 * 
 */
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
@Test(suiteName = "CategoryDAOTestCase")
public class CategoryDAOTestCase extends AbstractTestNGSpringContextTests {

	private static final Log	LOGGER	= LogFactory
	                                           .getLog(CategoryDAOTestCase.class
	                                                   .getName());

	@Autowired
	@Qualifier("categorydao")
	private CategoryDAO	     categorydao;

	@Autowired
	@Qualifier("entityfactory")
	private EntityFactory	 entityfactory;

	@Test
	public void insert() {
		LOGGER.info("insert - starting...");
		Category category = (Category) entityfactory
		        .createDomainEntity("category");
		Number id = categorydao.insert(category);
		try {
			Assert.assertNotNull(id);
			Assert.assertEquals(category.getName(),
			        ((Category) categorydao.select(id)).getName());
			category.setId((Long) id);
			categorydao.delete(category);
		} catch (Exception e) {
		}
		LOGGER.info("insert - end.");
	}

	@Test
	public void select() {
		LOGGER.info("select - starting...");
		Category category = (Category) entityfactory
		        .createDomainEntity("category");
		Category category2 = (Category) entityfactory
		        .createDomainEntity("category");
		Number id = categorydao.insert(category);
		Number id2 = categorydao.insert(category2);
		try {
			Assert.assertNotNull(id);
			Assert.assertNotNull(id2);
			Assert.assertEquals(category.getName(),
			        ((Category) categorydao.select(id)).getName());
			Assert.assertEquals(category2.getName(),
			        ((Category) categorydao.select(id2)).getName());
			category.setId((Long) id);
			category2.setId((Long) id2);
			categorydao.delete(category);
			categorydao.delete(category2);
		} catch (Exception e) {
		}
		LOGGER.info("select - end.");
	}

	@Test
	public void update() {
		LOGGER.info("update - starting...");
		Category category = (Category) entityfactory
		        .createDomainEntity("category");
		Number id = categorydao.insert(category);
		category.setId((Long) id);
		category.setName("updated");
		try {
			categorydao.update(category);
			Assert.assertEquals("updated",
			        ((Category) categorydao.select(id)).getName());
			categorydao.delete(category);
		} catch (Exception e) {
		}
		LOGGER.info("update - end.");
	}

	@Test(expectedExceptions = {ObjectNotFoundException.class })
	public void delete() throws ObjectNotFoundException {
		LOGGER.info("delete - starting...");
		Category category = (Category) entityfactory
		        .createDomainEntity("category");
		Number id = categorydao.insert(category);
		category.setId((Long) id);
			categorydao.delete(category);
			categorydao.select(id);
		LOGGER.info("delete - end.");
	}

	@Test
	public void selectAll() {
		LOGGER.info("selectAll - starting...");
		Category category = (Category) entityfactory
		        .createDomainEntity("category");
		Category category2 = (Category) entityfactory
		        .createDomainEntity("category");
		Number id = categorydao.insert(category);
		Number id2 = categorydao.insert(category2);
		Assert.assertFalse(categorydao.selectAll().isEmpty());
		Assert.assertEquals(2, categorydao.selectAll().size());
		category.setId((Long) id);
		category2.setId((Long) id2);
		categorydao.delete(category);
		categorydao.delete(category2);
		LOGGER.info("selectAll - end.");
	}

	@Test
	public void selectByKey() {
		LOGGER.info("selectByKey - starting...");
		Category category = (Category) entityfactory
		        .createDomainEntity("category");
		Number id = categorydao.insert(category);
		List<DomainEntity> listCat = categorydao
		        .selectByKey(category.getName());
		Assert.assertEquals(category.getName(),
		        ((Category) listCat.get(0)).getName());
		category.setId((Long) id);
		categorydao.delete(category);
		LOGGER.info("selectByKey - end.");
	}

	// ====================Cache Testing===============================

	@Test
	public void selectCachedElement() {
		LOGGER.info("selectCachedElement - starting...");
		Category category = (Category) entityfactory
		        .createDomainEntity("category");
		Number id = categorydao.insert(category);
		category.setId((Long) id);
		categorydao.insertToCache(category);
		Assert.assertEquals(category.getName(), ((Category) categorydao
		        .selectCachedElement((Long) id, Category.class.getCanonicalName())).getName());
		categorydao.delete(category);
		LOGGER.info("selectCachedElement - end.");
	}

	@Test
	public void insertToCache() {
		LOGGER.info("insertToCache - starting...");
		Category category = (Category) entityfactory
		        .createDomainEntity("category");
		Category category2 = (Category) entityfactory
		        .createDomainEntity("category");
		Number id = categorydao.insert(category);
		Number id2 = categorydao.insert(category2);
		category.setId((Long) id);
		category2.setId((Long) id2);
		categorydao.insertToCache(category);
		categorydao.insertToCache(category2);
		Assert.assertEquals(category.getName(), ((Category) categorydao
		        .selectCachedElement((Long) id, Category.class.getCanonicalName())).getName());
		Assert.assertEquals(category2.getName(), ((Category) categorydao
		        .selectCachedElement((Long) id2, Category.class.getCanonicalName())).getName());
		categorydao.delete(category);
		categorydao.delete(category2);
		LOGGER.info("insertToCache - end.");
	}
}
